using System;
using System.Collections.Generic;
using System.Linq;

namespace DA.AnimGraph.Editor {

    /// <summary>
    /// 标记此类是哪个类型的model，可以从此类查找到目标类型
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
    public class ModelOfAttribute : Attribute {

        public readonly Type type;

        public ModelOfAttribute(Type type) {
            this.type = type;
        }

    }
    
    internal class NodeTypeRegister {
        private static NodeTypeRegister instance;
        public static NodeTypeRegister GetInstance() {
            if (instance == null) {
                instance = new();
            }
            return instance;
        }

        private NodeTypeRegister() {
            BuildTarget2Model();
            BuildNode2NodeTypeTuple();
        }

        /*
         * NodeMenuItemAttribute 删除Model参数
         * 
         * 通过 ModelOfAttribute 构建： name, model, node，nodeview
         * 菜单：从
         * 刷新：从 node 查询 nodeview
         * 
         * 通过 ModelOfAttribute 构建所有的 从目标查询model
         */

        Dictionary<Type, Type> target2Model; // 从目标类型查询model，目标类型是 AGANode 或 AGAPerk
        Dictionary<Type, NodeTypeTuple> nodeType2NodeTuple; // 从节点类型（agaNodeType）查询所有节点相关类型

        /// <summary>
        /// 获取菜单所需数据 (path, 类型信息)
        /// </summary>
        public NodeTypeTuple[] GetNodesForMenu() {
            return nodeType2NodeTuple.Values.Where(p => !string.IsNullOrEmpty(p.path)).ToArray();
        }

        public Type GetNodeViewTypeByAGANodeType(Type type) {
            if (nodeType2NodeTuple.TryGetValue(type, out var tuple)) {
                return tuple.nodeViewType;
            }
            return null;
        }
        
        public NodeTypeTuple GetNodeTypeTupleByAGANodeType(Type type) {
            if (nodeType2NodeTuple.TryGetValue(type, out var tuple)) {
                return tuple;
            }
            return null;
        }

        public Type GetModelTypeOf(Type nodeType) {
            if(target2Model.TryGetValue(nodeType, out var modelType)) {
                return modelType;
            }
            return null;
        }

        /// <summary>
        /// 通过 ModelOfAttribute 构建所有的 从目标类型查询model
        /// </summary>
        void BuildTarget2Model() {
            //查询所有 ModelOfAttribute
            var clsAndAttrList = TypeRegisterUtility.GetAllClassesByAttribute<ModelOfAttribute>();
            target2Model = new Dictionary<Type, Type>(clsAndAttrList.Count);
            foreach (var clsAndAttr in clsAndAttrList) {
                target2Model.Add(clsAndAttr.Item2.type, clsAndAttr.Item1);
            }
        }

        void BuildNode2NodeTypeTuple() {
            //查询所有 NodeMenuItemAttribute
            var clsAndAttrList = TypeRegisterUtility.GetAllClassesByAttribute<NodeMenuItemAttribute>();
            nodeType2NodeTuple = new(clsAndAttrList.Count);
            foreach (var clsAndAttr in clsAndAttrList) {
                //var name = Path.GetFileName(clsAndAttr.Item2.path);
                Type nodeModelType = GetModelTypeOf(clsAndAttr.Item2.agaNodeType);

                nodeType2NodeTuple.Add(clsAndAttr.Item2.agaNodeType, new NodeTypeTuple() {
                    agaNodeType = clsAndAttr.Item2.agaNodeType,
                    nodeModelType = nodeModelType,
                    nodeViewType = clsAndAttr.Item1,
                    path = clsAndAttr.Item2.path,
                });
            }
        }

    }

    internal class NodeTypeTuple {
        public Type agaNodeType;
        public Type nodeModelType;
        public Type nodeViewType;
        public string path;
    }


}
